package com.example.springboot.task.async.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/10/27 20:01
 */
@Service
@Slf4j
public class AsyncService {
    // 开启异步，spring会创建线程池来休眠
    // 异步方法，此时会立即响应而不是等待3s
    // Async注解仅支持返回void或future对象，其余对象会被回空
    @Async(value = "myThreadPool")
    public void hello() throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        Thread.sleep(3000);
        System.out.println("处理数据中");
    }

    public String hello_2() throws InterruptedException {
        Thread.sleep(3000);
        return "czk";
    }

    /**
     * 自定义线程池注入async
     *
     * @return
     */
    @Bean("myThreadPool")
    public Executor myThreadPool() {
        ThreadPoolTaskExecutor threadPoolExecutor = new ThreadPoolTaskExecutor();
        // 核心线程大小
        threadPoolExecutor.setCorePoolSize(8);
        // 最大线程大小
        threadPoolExecutor.setMaxPoolSize(16);
        // 队列容量
        threadPoolExecutor.setQueueCapacity(10);
        // 活跃时间
        threadPoolExecutor.setKeepAliveSeconds(100);
        // 线程名字前缀
        threadPoolExecutor.setThreadNamePrefix("czk-");
        // 初始化
        threadPoolExecutor.initialize();
        return threadPoolExecutor;
    }

    @Async(value = "myThreadPool")
    public CompletableFuture<String> doTaskOne() throws Exception {
        log.info("开始做任务一");
        long start = System.currentTimeMillis();
        Thread.sleep(ThreadLocalRandom.current().nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("完成任务一，耗时：" + (end - start) + "毫秒");
        return CompletableFuture.completedFuture("任务一完成");
    }


    @Async(value = "myThreadPool") //   指定线程池
    public CompletableFuture<String> doTaskTwo() throws Exception {
        log.info("开始做任务二");
        long start = System.currentTimeMillis();
        Thread.sleep(ThreadLocalRandom.current().nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("完成任务二，耗时：" + (end - start) + "毫秒");
        return CompletableFuture.completedFuture("任务一完成");
    }

    @Async(value = "myThreadPool")
    public CompletableFuture<String> doTaskThree() throws Exception {
        log.info("开始做任务三");
        long start = System.currentTimeMillis();
        Thread.sleep(ThreadLocalRandom.current().nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("完成任务三，耗时：" + (end - start) + "毫秒");
        return CompletableFuture.completedFuture("任务一完成");
    }

    /**
     * 测试支持注解的spel表达式
     *
     */
    @Async(value = "${my.pool}")
    public void testSpel(){
        System.out.println("线程池名称===="+Thread.currentThread().getName());
    }
}
